#include <jni.h>
#include <string>
#include <vector>
#include <android/log.h>

#define LOG_TAG "MyJNI"

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

using namespace std;

void printAndroidLog(JNIEnv *env,jstring message);
void call_back(JNIEnv *env, jobject obj, const char *string1);
static vector<jstring> vMessages;
// 全局变量，用于存储回调对象的全局引用
static jobject globalCallbackObject;

jint intFromJNI(JNIEnv* env,jobject job);
//创建JNINativeMethod数组来映射函数stringFromJNI。
//其中stringFromJNI是Java层的函数名，"()Ljava/lang/String;"是入参/返回值类型的字符，(jstring*)stringFromJNI 是当前native函数的指针
static const JNINativeMethod gMethods[] = {
        {"intFromJNI", "()I", (jint *)intFromJNI}
};

JNIEXPORT jint JNI_OnLoad(JavaVM* jvm,void* reserved){
    __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,"执行了JNI_OnLoad");
    JNIEnv* env = NULL;
    if(jvm->GetEnv((void **)(&env),JNI_VERSION_1_4)!=JNI_OK)
        return -1;
    //此时env得到了JNIEnv
    jclass clazz=env->FindClass("com/xunua/MyFecDemo/MainActivity");
    if (!clazz){
        __android_log_print(ANDROID_LOG_INFO, "native", "cannot get class: com/xunua/MyFecDemo/MainActivity");
        return -1;
    }
    //开始注册native函数
    env->RegisterNatives(clazz,gMethods,sizeof(gMethods)/sizeof(gMethods[0]));
    return JNI_VERSION_1_4;
}

jint intFromJNI(JNIEnv* env,jobject job){
    int result = 20;
    return result;
}

extern "C" JNIEXPORT jstring JNICALL
Java_com_xunua_MyFecDemo_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject job) {
    string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

extern "C" JNIEXPORT void JNICALL
Java_com_xunua_MyFecDemo_MainActivity_putDecodeString (JNIEnv *env, jobject thiz, jstring message,jint request_code) {
    vMessages.push_back(message);
    printAndroidLog(env,message);
}

void printAndroidLog(JNIEnv *env,jstring message){
    // 将jstring转换为C风格的字符串
    const char *nativeString = env->GetStringUTFChars(message, nullptr);
    // 打印信息到Logcat
    LOGI("Content of jstring: %s", nativeString);

    call_back(env, globalCallbackObject, nativeString);

    // 释放获取的jstring
    env->ReleaseStringUTFChars(message, nativeString);
}

void call_back(JNIEnv *env, jobject obj, const char *string1) {
    if (env == nullptr || obj == nullptr || string1== nullptr) return;
    // 获取CallbackExample对象的class
    jclass clazz = env->GetObjectClass(obj);

    // 获取CallbackExample对象的实例方法ID
    jmethodID receiveCallbackMethod = env->GetMethodID(clazz, "receiveCallback", "(Ljava/lang/String;)V");

    // 调用Java对象的回调方法
    if (receiveCallbackMethod != nullptr) {
        // 创建一个Java字符串作为回调参数
        jstring message = env->NewStringUTF(string1);

        // 调用回调方法
        env->CallVoidMethod(obj, receiveCallbackMethod, message);

        // 释放创建的Java字符串
        env->DeleteLocalRef(message);
    }
}

extern "C" JNIEXPORT void JNICALL
Java_com_xunua_MyFecDemo_CallbackExample_callNativeMethod(JNIEnv *env, jobject obj) {
    // 保存回调对象的全局引用
    globalCallbackObject = env->NewGlobalRef(obj);
    call_back(env,obj,"123123123");
}

extern "C" //表示以C的语法来编译
JNIEXPORT jstring JNICALL   //函数签名信息，表示返回值为jstring->string类型。
Java_com_xunua_MyFecDemo_NativeLibManager_getString(JNIEnv *env, jobject thiz) {
    string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}extern "C"


extern "C"
JNIEXPORT void JNICALL
Java_com_xunua_MyFecDemo_MainActivity_func3(JNIEnv *env, jobject thiz) {
    jclass clazz=env->GetObjectClass(thiz);
    //拿到java中两个成员的id
    jfieldID mName = env->GetFieldID(clazz,"mName","Ljava/lang/String;");
    jfieldID num = env->GetFieldID(clazz,"num","I");
    //修改他们的值
    env->SetObjectField(thiz,mName,env->NewStringUTF("哈哈哈，被JNI改了"));
    env->SetIntField(thiz,num,50);
}


extern "C"
JNIEXPORT void JNICALL
Java_com_xunua_MyFecDemo_MainActivity_func4(JNIEnv *env, jobject thiz) {
    jclass clazz=env->GetObjectClass(thiz);
    //获取函数ID
    jmethodID onCallbackId = env->GetMethodID(clazz,"onCallback","(I)V");
    env->CallVoidMethod(thiz,onCallbackId,123);
}